package com.maistars.spider.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.maistars.spider.common.exception.TopicSpiderException;
import com.maistars.spider.repository.dao.CrawlerTaskDao;
import com.maistars.spider.repository.model.CrawlerFieldRulePO;
import com.maistars.spider.repository.model.CrawlerPageRulePO;
import com.maistars.spider.repository.model.CrawlerTaskPO;
import com.maistars.spider.view.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author dhr
 * @date 2022/1/22 12:01 上午
 */
@Controller
@RequestMapping("/pageRule")
@Slf4j
public class PageRuleController {

    @Autowired
    private CrawlerTaskDao crawlerTaskDao;

    /**
     * 创建页面规则
     */
    @RequestMapping("/createPageRule")
    @ResponseBody
    public ResponseResult<Boolean> createPageRule(HttpServletRequest request) {
        String pageType = request.getParameter("pageType");
        String pageContentType = request.getParameter("pageContentType");
        String ruleName = request.getParameter("ruleName");
        String taskId = request.getParameter("taskId");
        /**
         * {parseType:"",parseRule:1,params:{}}
         */
        String urlRule = request.getParameter("urlRule");
        String pageTurnRule = request.getParameter("pageTurnRule");
        String level = request.getParameter("level");
        String parentRuleId = request.getParameter("parentRuleId");

        CrawlerPageRulePO pageRulePO = new CrawlerPageRulePO();
        pageRulePO.setParentRuleId(Integer.parseInt(parentRuleId));
        pageRulePO.setLevel(Integer.parseInt(level));
        pageRulePO.setPageType(Integer.parseInt(pageType));
        pageRulePO.setPageContentType(Integer.parseInt(pageContentType));
        pageRulePO.setRuleName(ruleName);
        pageRulePO.setTaskId(Integer.parseInt(taskId));
        pageRulePO.setUrlRule(urlRule);
        pageRulePO.setPageTurnRule(pageTurnRule == null ? null : JSONObject.toJSONString(pageTurnRule));
        pageRulePO.setStatus(0);

        ResponseResult<Boolean> responseResult = new ResponseResult<Boolean>();
        responseResult.setCode(100);
        try {
            crawlerTaskDao.createCrawlerPageRule(pageRulePO);
            responseResult.setData(true);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("增加任务出错");
        }
        return responseResult;

    }

    /**
     * 创建页面规则
     */
    @RequestMapping("/updatePageRule")
    @ResponseBody
    public ResponseResult<Boolean> updatePageRule(HttpServletRequest request) {
        String pageRuleId = request.getParameter("pageRuleId");
        String pageType = request.getParameter("pageType");
        String pageContentType = request.getParameter("pageContentType");
        String ruleName = request.getParameter("ruleName");
        String taskId = request.getParameter("taskId");
        /**
         * {parseType:"",parseRule:1,params:{}}
         */
        String pageTurnRule = request.getParameter("pageTurnRule");
        String level = request.getParameter("level");
        String parentRuleId = request.getParameter("parentRuleId");

        ResponseResult<Boolean> responseResult = new ResponseResult<Boolean>();
        responseResult.setCode(100);
        try {
            CrawlerPageRulePO pageRulePO = crawlerTaskDao.getCrawlerPageRule(Integer.parseInt(pageRuleId));
            pageRulePO.setParentRuleId(Integer.parseInt(parentRuleId));
            pageRulePO.setLevel(Integer.parseInt(level));
            pageRulePO.setPageType(Integer.parseInt(pageType));
            pageRulePO.setPageContentType(Integer.parseInt(pageContentType));
            pageRulePO.setRuleName(ruleName);
            pageRulePO.setTaskId(Integer.parseInt(taskId));
            pageRulePO.setPageTurnRule(pageTurnRule == null ? null : JSONObject.toJSONString(pageTurnRule));
            pageRulePO.setStatus(0);

            crawlerTaskDao.updateCrawlerPageRule(pageRulePO);
            responseResult.setData(true);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("更新页面规则出错");
        }
        return responseResult;
    }

    /**
     * 创建页面规则
     */
    @RequestMapping("/deletePageRule")
    @ResponseBody
    public ResponseResult<Boolean> deletePageRule(HttpServletRequest request) {
        String pageRuleId = request.getParameter("pageRuleId");
        ResponseResult<Boolean> responseResult = new ResponseResult<Boolean>();
        responseResult.setCode(100);
        try {
            // 如果有字段规则，先把页面规则下的字段规则删除
            List<CrawlerFieldRulePO> crawlerFieldRulePOS = crawlerTaskDao.listCrawlerFieldRules(Integer.parseInt(pageRuleId));
            for(CrawlerFieldRulePO crawlerFieldRulePO:crawlerFieldRulePOS){
                CrawlerFieldRulePO newCrawlerFieldRulePO = new CrawlerFieldRulePO();
                newCrawlerFieldRulePO.setId(crawlerFieldRulePO.getId());
                newCrawlerFieldRulePO.setStatus(-1);
                crawlerTaskDao.updateCrawlerFieldRule(newCrawlerFieldRulePO);
            }
            // 字段规则删完后，删除页面规则
            CrawlerPageRulePO pageRulePO = crawlerTaskDao.getCrawlerPageRule(Integer.parseInt(pageRuleId));
            pageRulePO.setStatus(-1);
            crawlerTaskDao.updateCrawlerPageRule(pageRulePO);
            responseResult.setData(true);
        } catch (Throwable e) {
            responseResult.setCode(400);
            responseResult.setMsg("删除页面规则出错");
        }
        return responseResult;
    }

    @GetMapping("/showPageRulesSetting")
    public String showPageRulesSetting(Model model, HttpServletRequest request) {
        String taskId = request.getParameter("taskId");
        try {
            CrawlerTaskPO crawlerTaskPO = crawlerTaskDao.getCrawlerTask(Integer.parseInt(taskId));
            model.addAttribute("taskName", crawlerTaskPO.getTaskName());
        } catch (Throwable e) {
            e.printStackTrace();
        }
        model.addAttribute("taskId", taskId);
        return "page/task-pagerules-setting";
    }

    @GetMapping("/showPageruleAdd")
    public String showTaskPageRulesAdd(Model model, HttpServletRequest request) {
        String taskId = request.getParameter("taskId");
        String parentPageRuleId = request.getParameter("parentPageRuleId");

        String taskName = "";
        String parentPageRuleName = "";
        int parentLevel = 0;
        // 获取任务ID
        try {
            CrawlerTaskPO crawlerTaskPO = crawlerTaskDao.getCrawlerTask(Integer.parseInt(taskId));
            if (crawlerTaskPO != null) {
                taskName = crawlerTaskPO.getTaskName();
            }

            if (Integer.parseInt(parentPageRuleId) == -1) {
                parentPageRuleName = "根规则";
            } else {
                CrawlerPageRulePO parentPageRulePO = crawlerTaskDao.getCrawlerPageRule(Integer.parseInt(parentPageRuleId));
                if (parentPageRulePO != null) {
                    parentPageRuleName = parentPageRulePO.getRuleName();
                    parentLevel = parentPageRulePO.getLevel();
                }
            }
        } catch (TopicSpiderException e) {
            log.error("get crawler task occured error", e);
        }

        model.addAttribute("taskId", taskId);
        model.addAttribute("parentPageRuleId", parentPageRuleId);
        model.addAttribute("taskName", taskName);
        model.addAttribute("parentPageRuleName", parentPageRuleName);
        model.addAttribute("parentLevel", parentLevel);
        return "page/table/task-pagerule-operation";
    }

    @GetMapping("/showPageruleEdit")
    public String showTaskPageRulesEdit(Model model, HttpServletRequest request) {
        String taskId = request.getParameter("taskId");
        String pageRuleId = request.getParameter("pageRuleId");

        String taskName = "";
        String parentPageRuleName = "";
        int parentLevel = 0;
        // 获取任务ID
        try {
            CrawlerTaskPO crawlerTaskPO = crawlerTaskDao.getCrawlerTask(Integer.parseInt(taskId));
            if (crawlerTaskPO != null) {
                taskName = crawlerTaskPO.getTaskName();
            }

            // 获取当前页规则信息
            CrawlerPageRulePO pageRulePO = crawlerTaskDao.getCrawlerPageRule(Integer.parseInt(pageRuleId));

            // 获取父规则信息
            int parentPageRuleId = pageRulePO.getParentRuleId();
            if (parentPageRuleId == -1) {
                parentPageRuleName = "根规则";
            } else {
                CrawlerPageRulePO parentPageRulePO = crawlerTaskDao.getCrawlerPageRule(parentPageRuleId);
                if (parentPageRulePO != null) {
                    parentPageRuleName = parentPageRulePO.getRuleName();
                    parentLevel = parentPageRulePO.getLevel();
                }
            }

            model.addAttribute("parentPageRuleId", pageRulePO.getParentRuleId());
            model.addAttribute("taskId", taskId);
            model.addAttribute("taskName", taskName);
            model.addAttribute("parentPageRuleName", parentPageRuleName);
            model.addAttribute("parentLevel", parentLevel);
            model.addAttribute("pageRuleDO", pageRulePO);
        } catch (TopicSpiderException e) {
            log.error("get crawler task occured error", e);
        }
        return "page/table/task-pagerule-operation";
    }

    @GetMapping("/data/listAllPageRules")
    @ResponseBody
    public ResponseResult<List<Map<String, Object>>> listAllPageRules(HttpServletRequest request) {
        String taskId = request.getParameter("taskId");

        ResponseResult<List<Map<String, Object>>> responseResult = new ResponseResult<>();
        responseResult.setData(new ArrayList<>());
        responseResult.setCode(100);

        // 根据任务ID获取全部页面配置规则
        try {
            List<CrawlerPageRulePO> pageRules = crawlerTaskDao.listCrawlerPageRules(Integer.parseInt(taskId));
            if (pageRules != null && !pageRules.isEmpty()) {
                for (CrawlerPageRulePO crawlerPageRulePO : pageRules) {
                    Map<String, Object> result = new HashMap<>();
                    result.put("id", crawlerPageRulePO.getId());
                    result.put("level", crawlerPageRulePO.getLevel());
                    result.put("ruleName", crawlerPageRulePO.getRuleName());
                    result.put("taskId", crawlerPageRulePO.getTaskId());
                    result.put("parentId", crawlerPageRulePO.getParentRuleId());
                    result.put("pageType", crawlerPageRulePO.getPageType());
                    JSONObject urlRule = JSONObject.parseObject(crawlerPageRulePO.getUrlRule());
                    result.put("parseType", urlRule.getIntValue("parseType"));
                    result.put("pageContentType", crawlerPageRulePO.getPageContentType());
                    result.put("parseRule", null);
                    responseResult.getData().add(result);

                    List<CrawlerFieldRulePO> fieldRulePOS = crawlerTaskDao.listCrawlerFieldRules(crawlerPageRulePO.getId());
                    if (crawlerPageRulePO.getPageType() == 1) {
                        // 列表页查询第一个field规则
                        if (fieldRulePOS != null && !fieldRulePOS.isEmpty()) {
                            result.put("parseRule", fieldRulePOS.get(0).getRule());
                        }
                    } else {
                        result.put("fieldRuleCount", fieldRulePOS != null ? fieldRulePOS.size() : 0);
                        int count = 1;
                        for (CrawlerFieldRulePO crawlerFieldRulePO : fieldRulePOS) {
                            result = new HashMap<>();
                            result.put("id", crawlerFieldRulePO.getPageRuleId()+count++);
                            result.put("isFieldRule", 1);
                            result.put("taskId", crawlerPageRulePO.getTaskId());
                            result.put("ruleName", crawlerFieldRulePO.getFieldName());
                            result.put("parentId", crawlerFieldRulePO.getPageRuleId());
                            result.put("pageType", crawlerPageRulePO.getPageType());
                            result.put("parseType", crawlerFieldRulePO.getParseType());
                            result.put("parseRule", crawlerFieldRulePO.getRule());
                            responseResult.getData().add(result);
                        }
                    }
                }

            }
        } catch (TopicSpiderException e) {
            responseResult.setCode(400);
            responseResult.setMsg("获取页面配置规则出错");
            log.error("listAllPageRules error", e);
            return responseResult;
        }
        return responseResult;
    }

    /**
     * 创建字段规则
     */
    @RequestMapping("/saveFieldRules")
    @ResponseBody
    public ResponseResult<Boolean> createFieldRules(HttpServletRequest request) {
        ResponseResult<Boolean> responseResult = new ResponseResult<Boolean>();
        responseResult.setCode(100);

        try {
            String pageType = request.getParameter("pageType");
            String pageRuleId = request.getParameter("pageRuleId");
            String parseType = request.getParameter("parseType");
            String sampleUrl = request.getParameter("sampleUrl");
            String renderConfig = request.getParameter("renderConfig");

            JSONObject fieldRulesObj = JSONObject.parseObject(request.getParameter("fieldRules"));

            if (pageRuleId == null) {
                responseResult.setCode(400);
                responseResult.setMsg("can't find page rule");
                return responseResult;
            }

            CrawlerPageRulePO crawlerPageRulePO = crawlerTaskDao.getCrawlerPageRule(Integer.valueOf(pageRuleId));
            if (crawlerPageRulePO == null) {
                responseResult.setCode(400);
                responseResult.setMsg("can't find page rule");
                return responseResult;
            }

            // 更新pageRule
            CrawlerPageRulePO newCrawPageRulePO = new CrawlerPageRulePO();
            newCrawPageRulePO.setId(crawlerPageRulePO.getId());
            JSONObject urlRule = JSONObject.parseObject(crawlerPageRulePO.getUrlRule());
            urlRule.put("sampleUrl", sampleUrl);
            newCrawPageRulePO.setUrlRule(urlRule.toJSONString());
            newCrawPageRulePO.setRenderConfig(renderConfig);
            crawlerTaskDao.updateCrawlerPageRule(newCrawPageRulePO);

            // 删除废弃的字段
            JSONArray deleteFieldRules = fieldRulesObj.getJSONArray("delete");

            for (int i = 0; i < deleteFieldRules.size(); i++) {
                CrawlerFieldRulePO crawlerFieldRulePO = new CrawlerFieldRulePO();
                crawlerFieldRulePO.setId(deleteFieldRules.getInteger(i));
                crawlerFieldRulePO.setStatus(-1);
                crawlerTaskDao.updateCrawlerFieldRule(crawlerFieldRulePO);
            }

            // 获取待更新字段，并进行判断
            JSONArray updateFieldRules = fieldRulesObj.getJSONArray("update");
            for (int i = 0; i < updateFieldRules.size(); i++) {
                JSONObject fieldRule = updateFieldRules.getJSONObject(i);
                String serverId = fieldRule.getString("serverId");
                String fieldName = fieldRule.getString("fieldName");
                String rule = fieldRule.getString("rule");
                String processConfig = fieldRule.getString("processConfig");

                // 查询已存在的field rule并更新
                if (serverId == null) {
                    continue;
                }
                CrawlerFieldRulePO crawlerFieldRulePO = new CrawlerFieldRulePO();
                crawlerFieldRulePO.setId(Integer.parseInt(serverId));
                crawlerFieldRulePO.setFieldName(fieldName);
                // xpath的解析规则就是xpath表达式
                crawlerFieldRulePO.setRule(rule);
                // 处理的JSON串，根据parseType的不同，表现方式不同
                crawlerFieldRulePO.setProcessConfig(processConfig);
                crawlerFieldRulePO.setStatus(0);

                crawlerTaskDao.updateCrawlerFieldRule(crawlerFieldRulePO);
            }

            // 获取待新增的字段信息
            JSONArray addFieldRules = fieldRulesObj.getJSONArray("add");

            for (int i = 0; i < addFieldRules.size(); i++) {
                JSONObject fieldRule = addFieldRules.getJSONObject(i);
                String fieldId = fieldRule.getString("fieldId");
                String fieldName = fieldRule.getString("fieldName");
                String rule = fieldRule.getString("rule");
                String processConfig = fieldRule.getString("processConfig");

                // 根据fieldName查一遍
                CrawlerFieldRulePO crawlerFieldRulePO = crawlerTaskDao.getCrawlerFieldRuleByName(fieldId, Integer.parseInt(pageRuleId));
                boolean isCreated = false;
                if (crawlerFieldRulePO == null) {
                    crawlerFieldRulePO = new CrawlerFieldRulePO();
                    isCreated = true;
                }

                crawlerFieldRulePO.setFieldId(fieldId);
                crawlerFieldRulePO.setFieldName(fieldName);
                crawlerFieldRulePO.setPageRuleId(Integer.parseInt(pageRuleId));
                crawlerFieldRulePO.setParseType(Integer.parseInt(parseType));
                // xpath的解析规则就是xpath表达式
                crawlerFieldRulePO.setRule(rule);
                // 处理的JSON串，根据parseType的不同，表现方式不同
                crawlerFieldRulePO.setProcessConfig(processConfig);
                crawlerFieldRulePO.setStatus(0);

                if (isCreated) {
                    crawlerTaskDao.createCrawlerFieldRule(crawlerFieldRulePO);
                } else {
                    crawlerTaskDao.updateCrawlerFieldRule(crawlerFieldRulePO);
                }
            }

        } catch (TopicSpiderException e) {
            responseResult.setCode(400);
            responseResult.setMsg("保存字段成功");
            log.error("get crawler task occured error", e);
        }
        return responseResult;
    }

    /**
     * 清除被删除的字段
     */
    @RequestMapping("/deleteFieldRules")
    @ResponseBody
    public ResponseResult<Boolean> deleteFieldRules(HttpServletRequest request) {
        ResponseResult<Boolean> responseResult = new ResponseResult<Boolean>();
        responseResult.setCode(100);

        String serverIds = request.getParameter("serverIds");
        JSONArray serverIdArray = JSONArray.parseArray(serverIds);

        try {
            for (int i = 0; i < serverIdArray.size(); i++) {
                CrawlerFieldRulePO crawlerFieldRulePO = new CrawlerFieldRulePO();
                crawlerFieldRulePO.setId(serverIdArray.getInteger(i));
                crawlerFieldRulePO.setStatus(-1);
                crawlerTaskDao.updateCrawlerFieldRule(crawlerFieldRulePO);
            }
        } catch (TopicSpiderException e) {
            responseResult.setCode(400);
            responseResult.setMsg("清除字段出错");
            log.error("get crawler task occured error", e);
        }
        return responseResult;
    }

    @GetMapping("/listAllFieldRule")
    @ResponseBody
    public ResponseResult<Map<String, Object>> listAllFieldRule(Model model, HttpServletRequest request) {
        String pageRuleId = request.getParameter("pageRuleId");

        ResponseResult<Map<String, Object>> responseResult = new ResponseResult<>();
        responseResult.setData(new HashMap<>());
        responseResult.setCode(100);

        List<CrawlerFieldRulePO> crawlerFieldRulePOS = new ArrayList<>();

        try {
            CrawlerPageRulePO crawlerPageRulePO = crawlerTaskDao.getCrawlerPageRule(Integer.parseInt(pageRuleId));

            List<CrawlerFieldRulePO> fieldRulePOS = crawlerTaskDao.listCrawlerFieldRules(Integer.parseInt(pageRuleId));
            if (fieldRulePOS != null) {
                crawlerFieldRulePOS.addAll(fieldRulePOS);
            }
            responseResult.getData().put("fieldRules",crawlerFieldRulePOS);
            responseResult.getData().put("renderConfig",crawlerPageRulePO.getRenderConfig()==null?"{}":crawlerPageRulePO.getRenderConfig());
        } catch (TopicSpiderException e) {
            responseResult.setCode(400);
            responseResult.setMsg("获取页面配置规则出错");
            log.error("listAllFieldRule error", e);
            return responseResult;
        }
        return responseResult;
    }

}
